#Load libraries



library(TCGAWorkflowData)
library(TCGAbiolinks)
package ‘TCGAbiolinks’ was built under R version 4.1.2Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
 =============================================================
 ______  ___  ____   ___                                        
   ||   |    |      |   | |    o  __  |   o  _         __         
   ||   |    | ___  |___| |__  | |  | |   | | | | |_/ |__         
   ||   |___ |____| |   | |__| | |__| |__ | | |_| | \  __|       
 ------------------------------------------------------------
 Query, download & analyze - GDC                  
 Version:2.22.4
 ==============================================================
library(SummarizedExperiment)
Loading required package: MatrixGenerics
Loading required package: matrixStats
package ‘matrixStats’ was built under R version 4.1.2
Attaching package: ‘MatrixGenerics’

The following objects are masked from ‘package:matrixStats’:

    colAlls, colAnyNAs, colAnys, colAvgsPerRowSet, colCollapse, colCounts, colCummaxs, colCummins,
    colCumprods, colCumsums, colDiffs, colIQRDiffs, colIQRs, colLogSumExps, colMadDiffs, colMads,
    colMaxs, colMeans2, colMedians, colMins, colOrderStats, colProds, colQuantiles, colRanges,
    colRanks, colSdDiffs, colSds, colSums2, colTabulates, colVarDiffs, colVars, colWeightedMads,
    colWeightedMeans, colWeightedMedians, colWeightedSds, colWeightedVars, rowAlls, rowAnyNAs,
    rowAnys, rowAvgsPerColSet, rowCollapse, rowCounts, rowCummaxs, rowCummins, rowCumprods,
    rowCumsums, rowDiffs, rowIQRDiffs, rowIQRs, rowLogSumExps, rowMadDiffs, rowMads, rowMaxs,
    rowMeans2, rowMedians, rowMins, rowOrderStats, rowProds, rowQuantiles, rowRanges, rowRanks,
    rowSdDiffs, rowSds, rowSums2, rowTabulates, rowVarDiffs, rowVars, rowWeightedMads,
    rowWeightedMeans, rowWeightedMedians, rowWeightedSds, rowWeightedVars

Loading required package: GenomicRanges
package ‘GenomicRanges’ was built under R version 4.1.2Loading required package: stats4
Loading required package: BiocGenerics

Attaching package: ‘BiocGenerics’

The following objects are masked from ‘package:stats’:

    IQR, mad, sd, var, xtabs

The following objects are masked from ‘package:base’:

    anyDuplicated, append, as.data.frame, basename, cbind, colnames, dirname, do.call, duplicated,
    eval, evalq, Filter, Find, get, grep, grepl, intersect, is.unsorted, lapply, Map, mapply,
    match, mget, order, paste, pmax, pmax.int, pmin, pmin.int, Position, rank, rbind, Reduce,
    rownames, sapply, setdiff, sort, table, tapply, union, unique, unsplit, which.max, which.min

Loading required package: S4Vectors
package ‘S4Vectors’ was built under R version 4.1.3
Attaching package: ‘S4Vectors’

The following objects are masked from ‘package:base’:

    expand.grid, I, unname

Loading required package: IRanges
Loading required package: GenomeInfoDb
package ‘GenomeInfoDb’ was built under R version 4.1.2Loading required package: Biobase
Welcome to Bioconductor

    Vignettes contain introductory material; view with 'browseVignettes()'. To cite Bioconductor,
    see 'citation("Biobase")', and for packages 'citation("pkgname")'.


Attaching package: ‘Biobase’

The following object is masked from ‘package:MatrixGenerics’:

    rowMedians

The following objects are masked from ‘package:matrixStats’:

    anyMissing, rowMedians
library(edgeR)
Loading required package: limma
package ‘limma’ was built under R version 4.1.3
Attaching package: ‘limma’

The following object is masked from ‘package:BiocGenerics’:

    plotMA
library(EnhancedVolcano)
Loading required package: ggplot2
package ‘ggplot2’ was built under R version 4.1.2Loading required package: ggrepel
Registered S3 methods overwritten by 'ggalt':
  method                  from   
  grid.draw.absoluteGrob  ggplot2
  grobHeight.absoluteGrob ggplot2
  grobWidth.absoluteGrob  ggplot2
  grobX.absoluteGrob      ggplot2
  grobY.absoluteGrob      ggplot2
library(Seurat)
package ‘Seurat’ was built under R version 4.1.2Attaching SeuratObject
Attaching sp

Attaching package: ‘Seurat’

The following object is masked from ‘package:SummarizedExperiment’:

    Assays
library(lumi)
Setting options('download.file.method.GEOquery'='auto')
Setting options('GEOquery.inmemory.gpl'=FALSE)
No methods found in package ‘RSQLite’ for request: ‘dbListFields’ when loading ‘lumi’
library(tidyverse)
── Attaching packages ────────────────────────────────────────────────────────────────────── tidyverse 1.3.1 ──
✔ tibble  3.1.7     ✔ dplyr   1.0.9
✔ tidyr   1.2.0     ✔ stringr 1.4.0
✔ readr   2.1.2     ✔ forcats 0.5.1
✔ purrr   0.3.4     
package ‘tibble’ was built under R version 4.1.2package ‘tidyr’ was built under R version 4.1.2package ‘readr’ was built under R version 4.1.2package ‘dplyr’ was built under R version 4.1.2── Conflicts ───────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::collapse()   masks IRanges::collapse()
✖ dplyr::combine()    masks lumi::combine(), Biobase::combine(), BiocGenerics::combine()
✖ dplyr::count()      masks matrixStats::count()
✖ dplyr::desc()       masks IRanges::desc()
✖ tidyr::expand()     masks S4Vectors::expand()
✖ dplyr::filter()     masks stats::filter()
✖ dplyr::first()      masks S4Vectors::first()
✖ dplyr::lag()        masks stats::lag()
✖ ggplot2::Position() masks BiocGenerics::Position(), base::Position()
✖ purrr::reduce()     masks GenomicRanges::reduce(), IRanges::reduce()
✖ dplyr::rename()     masks S4Vectors::rename()
✖ dplyr::slice()      masks IRanges::slice()
options(ggrepel.max.overlaps = Inf)

#Load TCGA annotations

mrna_query <- GDCquery(project = "TCGA-PRAD",
                      data.category = "Transcriptome Profiling",
                      data.type = "Gene Expression Quantification",
                      workflow.type = "STAR - Counts")
--------------------------------------
o GDCquery: Searching in GDC database
--------------------------------------
Genome of reference: hg38
--------------------------------------------
oo Accessing GDC. This might take a while...
--------------------------------------------
ooo Project: TCGA-PRAD
--------------------
oo Filtering results
--------------------
ooo By data.type
ooo By workflow.type
----------------
oo Checking data
----------------
ooo Check if there are duplicated cases
ooo Check if there results for the query
-------------------
o Preparing output
-------------------
mrna_query$results[[1]]



nrml_meta <- mrna_query$results[[1]] %>% dplyr::filter(sample_type == "Solid Tissue Normal")
#GDCdownload(mrna_query, method = "api", directory = "/Users/ds/Desktop")

#Process normal prostate counts

full_path <- "/Users/ds/Desktop/projects/TCGA/TCGA-PRAD-Normal/harmonized/Transcriptome_Profiling/Gene_Expression_Quantification/"



nrml_rna <- do.call(cbind, lapply(list.files(path = full_path), FUN = function(f){
  print(paste0("processing: ",list.files(path = paste0(full_path, f))))
  counts <- read_tsv(file = list.files(path = paste0(full_path, f), full.names = T), skip = 6, col_names = F )
  
  return(data.frame(f = counts[,4]))
  
  
}))


symbols <- read_tsv(file = "/Users/ds/Desktop/projects/TCGA/TCGA-PRAD-Normal/harmonized/Transcriptome_Profiling/Gene_Expression_Quantification/0427d696-a33d-4005-ac1d-c5363754226e/b1becd71-bbed-4a0f-af9c-94b9b2af928b.rna_seq.augmented_star_gene_counts.tsv", skip = 6, col_names = F)[,2]
colnames(nrml_rna) <- list.files(path = full_path)




nrml_rna$Gene <- symbols$X2

write.table(x = nrml_rna, file = "/Users/ds/Desktop/projects/TCGA/TCGA-PRAD-Normal/normal_rna_counts.txt", quote = F, sep = "\t", row.names = F, col.names = T)

#Change IDS for normals

nrml_rna <- read.table(file = "/Users/ds/Desktop/projects/TCGA/TCGA-PRAD-Normal/normal_rna_counts.txt", header = T)


nrml_rna <- nrml_rna[!duplicated(nrml_rna$Gene),]


row.names(nrml_rna) <- nrml_rna$Gene 

nrml_rna <- dplyr::select(nrml_rna, -Gene)

colnames(nrml_rna) <- colnames(nrml_rna) %>% gsub(pattern = "^X*", replacement = "")

colnames(nrml_rna) <- colnames(nrml_rna) %>% gsub(pattern = "\\.", replacement = "-")



nrml_rna <-  cpm(nrml_rna, log = T) %>% t() %>% data.frame()#Log normalize
#nrml_rna <- nrml_rna %>% t() %>% data.frame()

nrml_rna <- nrml_rna %>% mutate(id = row.names(.), batch = "Normal") %>% merge(dplyr::select(nrml_meta , c(id, cases.submitter_id) ))
nrml_rna <- nrml_rna %>% mutate(cases = cases.submitter_id, Purity = NA, Grade_Mutational_status =NA)

#Download TCGA PRAD sample list


prad_meta<- mrna_query$results[[1]] %>% dplyr::filter(sample_type == "Primary Tumor")
#GDCdownload(mrna_query, method = "api", directory = "/Users/ds/Desktop")

#Process PRAD counts

full_path <- "/Users/ds/Desktop/projects/TCGA/TCGA-PRAD-Tumor/harmonized/Transcriptome_Profiling/Gene_Expression_Quantification/"

prad_rna <- do.call(cbind, lapply(list.files(path = full_path), FUN = function(f){
  print(paste0("processing: ",list.files(path = paste0(full_path, f))))
  counts <- read_tsv(file = list.files(path = paste0(full_path, f), full.names = T), skip = 6, col_names = F )
  
  return(data.frame(f = counts[,4]))
  
  
}))
#prad_rna <- cpm(prad_rna, log = T, prior.count = 1) %>% data.frame()
colnames(prad_rna) <- list.files(path = full_path)

symbols <- read_tsv(file = "/Users/ds/Desktop/projects/TCGA/TCGA-PRAD-Tumor/harmonized/Transcriptome_Profiling/Gene_Expression_Quantification/0007888f-8d96-4c01-8251-7fef6cc71596/88215dd0-5841-44f1-9393-eefd8238cbb3.rna_seq.augmented_star_gene_counts.tsv", skip = 6, col_names = F)[,2]

prad_rna$Gene <- symbols$X2


#write.table(x = prad_rna, file = "/Users/ds/Desktop/TCGA/TCGA-PRAD-Tumor/prad_rna_cpm.txt", quote = F, sep = "\t", row.names = F, col.names = T)

write.table(x = prad_rna, file = "/Users/ds/Desktop/projects/TCGA/TCGA-PRAD-Tumor/prad_rna_counts.txt", quote = F, sep = "\t", row.names = F, col.names = T)

#Format PRAD count data

prad_rna$Grade_Mutational_status
  [1]  7  6  7  7  7  6  7  7  7  9  7  8  7  7  7  7  7  9  7  6  6  7  7  6  7  7  9  7  7  7  6  6  7  6  6  7  6  7  7  9  9  6  8  9  7  6  9  7  7
 [50]  7  7  7  8  6  9  7  7  7  7  7  7  8  6  7  7  7  6  7  6  7  7  8  6  7  9  7  7  7  6  7  7  6  8  7  7  9  7  7  7  7  7  7  6  7  7  7  8  8
 [99]  6  7  7  8  7  7  7  9  7  9  6  6  9  8  6  7  8  7  6  6  7  8  7  8  9  7  6  9  6  7  7  7  6  7  7  8  7  7  7  7  9  8  7  6  6  9  7  8  7
[148]  8  7  7  7  7  7  6  7  7  7  6  6  7  9  7  7  8  6  6  9  9  6  8  7  7  9  6  7  9  7  9  7  7  9  6  8  9  7  6  7  7  8  7  9  8  9  7  8  7
[197]  8  7  8  8  7  7  7  6  9  6  6  7  6  8  6  7  8  7  7  6  6  9  7  6  7  7  7  7  7  6  7  7  6  7  7  7  6  6  7  7  7  7  7  7  9  6  8  7  7
[246]  7  8  8  7  6  7  8  6  7  8  7  9  6  8  8  8  6  9  9  7  7  7  7  8  7  9  9  7  7  7  7  8  7  7  7  8  7  7  7  7  8  9  7  7  7  7  7  7  6
[295]  9  7  6  7  6  8  9  7  7  6  7  7  7  6  6  7  7  8  6  7  7  8  7  8  9  6  7  7  6  8  7  9  7  7  9  7  7  7  9  7  7 10

#Add PRAD purity from GDC website

anno_prad <- read.csv(file = "/Users/ds/Desktop/projects/TCGA/TCGA-PRAD-Tumor/prad_supp.csv", header = T)
anno_prad <- anno_prad %>% dplyr::select(avgRNA_purity, PATIENT_ID, Reviewed_Gleason_sum)


prad_rna <- inner_join(prad_rna, anno_prad, by = c("cases.submitter_id" = "PATIENT_ID")) %>% mutate(Purity = avgRNA_purity * 100, cases = cases.submitter_id, Grade_Mutational_status = Reviewed_Gleason_sum)


anno_prad
NA

#Format mCRPC count data

anno_mcrpc <- read.table("/Users/ds/Desktop/projects/data/anno/202009_deepRNAseq_sample_full.txt", header =T)




anno_mcrpc <- anno_mcrpc %>% dplyr::select(c(sample_id, wgs_id, biopsy_site,tumor_purity_wgs, tumor_purity_rna , tumor_purity_hist, AR))


anno_mcrpc <- anno_mcrpc %>% mutate(cases =  sample_id, Purity = tumor_purity_rna, Grade_Mutational_status =AR) %>% dplyr::select(cases, Purity, Grade_Mutational_status)



mcrpc_rna <- read.table(file = "/Users/ds/Desktop/projects/data/rna/mCRPC_RNA_counts_genename.txt", header = T)
mcrpc_rna <- mcrpc_rna[!duplicated(mcrpc_rna$Genename),]




row.names(mcrpc_rna) <- mcrpc_rna$Genename
mcrpc_rna <- mcrpc_rna[,-1]
mcrpc_rna <- cpm(mcrpc_rna, log = T) %>% t() %>% data.frame()#Log normalize for heatmap
#mcrpc_rna <- mcrpc_rna %>% t() %>% data.frame()#Counts for DEG analysis
row.names(mcrpc_rna) <- gsub("\\.", "-",  x = row.names(mcrpc_rna))



mcrpc_rna <- mcrpc_rna %>% mutate(cases = row.names(.), batch = "mCRPC")

#Add mCRPC purity
mcrpc_rna <- mcrpc_rna %>% merge(anno_mcrpc)

#Merge PRAD and mCRPC datasets (DEG analysis)

#Merge PRAD, Normal, and mCRPC datasets (Heatmap)

query <- intersect(colnames(prad_rna), colnames(mcrpc_rna)) %>% intersect( colnames(nrml_rna))#Get lncRNAs in common + cases + purity

#Combine PRAD and mCRPC - rows are samples and columns are lncRNAs + RNA purity + batch
comb_rna <- rbind( nrml_rna[,query], arrange(prad_rna[,query],Grade_Mutational_status), arrange(mcrpc_rna[,query],Grade_Mutational_status))


comb_rna <- data.frame(comb_rna[,c("batch", "Purity", "cases", "Grade_Mutational_status")], comb_rna[,colnames(comb_rna) %in% c(pca_lncrna, notpca_lncrna)])


comb_rna <- comb_rna %>% mutate(cases = paste0(cases, ":", 1:nrow(comb_rna)))


row.names(comb_rna) <- comb_rna$cases
comb_rna$batch %>% table()
.
 mCRPC Normal   PRAD 
    74     52    336 

#Plotting heatmap of progression for prostate lncRNA

#Plot lncRNAs in TME

length(filt)
[1] 49
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKI0xvYWQgbGlicmFyaWVzCmBgYHtyfQoKCmxpYnJhcnkoVENHQVdvcmtmbG93RGF0YSkKbGlicmFyeShUQ0dBYmlvbGlua3MpCmxpYnJhcnkoU3VtbWFyaXplZEV4cGVyaW1lbnQpCmxpYnJhcnkoZWRnZVIpCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShsdW1pKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShwaGVhdG1hcCkKb3B0aW9ucyhnZ3JlcGVsLm1heC5vdmVybGFwcyA9IEluZikKCmBgYAoKCiNMb2FkIFRDR0EgYW5ub3RhdGlvbnMKYGBge3J9Cm1ybmFfcXVlcnkgPC0gR0RDcXVlcnkocHJvamVjdCA9ICJUQ0dBLVBSQUQiLAogICAgICAgICAgICAgICAgICAgICAgZGF0YS5jYXRlZ29yeSA9ICJUcmFuc2NyaXB0b21lIFByb2ZpbGluZyIsCiAgICAgICAgICAgICAgICAgICAgICBkYXRhLnR5cGUgPSAiR2VuZSBFeHByZXNzaW9uIFF1YW50aWZpY2F0aW9uIiwKICAgICAgICAgICAgICAgICAgICAgIHdvcmtmbG93LnR5cGUgPSAiU1RBUiAtIENvdW50cyIpCm1ybmFfcXVlcnkkcmVzdWx0c1tbMV1dCgoKCm5ybWxfbWV0YSA8LSBtcm5hX3F1ZXJ5JHJlc3VsdHNbWzFdXSAlPiUgZHBseXI6OmZpbHRlcihzYW1wbGVfdHlwZSA9PSAiU29saWQgVGlzc3VlIE5vcm1hbCIpCiNHRENkb3dubG9hZChtcm5hX3F1ZXJ5LCBtZXRob2QgPSAiYXBpIiwgZGlyZWN0b3J5ID0gIi9Vc2Vycy9kcy9EZXNrdG9wIikKYGBgCgojUHJvY2VzcyBub3JtYWwgcHJvc3RhdGUgY291bnRzCmBgYHtyfQpmdWxsX3BhdGggPC0gIi9Vc2Vycy9kcy9EZXNrdG9wL3Byb2plY3RzL1RDR0EvVENHQS1QUkFELU5vcm1hbC9oYXJtb25pemVkL1RyYW5zY3JpcHRvbWVfUHJvZmlsaW5nL0dlbmVfRXhwcmVzc2lvbl9RdWFudGlmaWNhdGlvbi8iCgoKCm5ybWxfcm5hIDwtIGRvLmNhbGwoY2JpbmQsIGxhcHBseShsaXN0LmZpbGVzKHBhdGggPSBmdWxsX3BhdGgpLCBGVU4gPSBmdW5jdGlvbihmKXsKICBwcmludChwYXN0ZTAoInByb2Nlc3Npbmc6ICIsbGlzdC5maWxlcyhwYXRoID0gcGFzdGUwKGZ1bGxfcGF0aCwgZikpKSkKICBjb3VudHMgPC0gcmVhZF90c3YoZmlsZSA9IGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlMChmdWxsX3BhdGgsIGYpLCBmdWxsLm5hbWVzID0gVCksIHNraXAgPSA2LCBjb2xfbmFtZXMgPSBGICkKICAKICByZXR1cm4oZGF0YS5mcmFtZShmID0gY291bnRzWyw0XSkpCiAgCiAgCn0pKQoKCnN5bWJvbHMgPC0gcmVhZF90c3YoZmlsZSA9ICIvVXNlcnMvZHMvRGVza3RvcC9wcm9qZWN0cy9UQ0dBL1RDR0EtUFJBRC1Ob3JtYWwvaGFybW9uaXplZC9UcmFuc2NyaXB0b21lX1Byb2ZpbGluZy9HZW5lX0V4cHJlc3Npb25fUXVhbnRpZmljYXRpb24vMDQyN2Q2OTYtYTMzZC00MDA1LWFjMWQtYzUzNjM3NTQyMjZlL2IxYmVjZDcxLWJiZWQtNGEwZi1hZjljLTk0YjliMmFmOTI4Yi5ybmFfc2VxLmF1Z21lbnRlZF9zdGFyX2dlbmVfY291bnRzLnRzdiIsIHNraXAgPSA2LCBjb2xfbmFtZXMgPSBGKVssMl0KY29sbmFtZXMobnJtbF9ybmEpIDwtIGxpc3QuZmlsZXMocGF0aCA9IGZ1bGxfcGF0aCkKCgoKCm5ybWxfcm5hJEdlbmUgPC0gc3ltYm9scyRYMgoKd3JpdGUudGFibGUoeCA9IG5ybWxfcm5hLCBmaWxlID0gIi9Vc2Vycy9kcy9EZXNrdG9wL3Byb2plY3RzL1RDR0EvVENHQS1QUkFELU5vcm1hbC9ub3JtYWxfcm5hX2NvdW50cy50eHQiLCBxdW90ZSA9IEYsIHNlcCA9ICJcdCIsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IFQpCmBgYAoKI0NoYW5nZSBJRFMgZm9yIG5vcm1hbHMKYGBge3J9Cm5ybWxfcm5hIDwtIHJlYWQudGFibGUoZmlsZSA9ICIvVXNlcnMvZHMvRGVza3RvcC9wcm9qZWN0cy9UQ0dBL1RDR0EtUFJBRC1Ob3JtYWwvbm9ybWFsX3JuYV9jb3VudHMudHh0IiwgaGVhZGVyID0gVCkKCgpucm1sX3JuYSA8LSBucm1sX3JuYVshZHVwbGljYXRlZChucm1sX3JuYSRHZW5lKSxdCgoKcm93Lm5hbWVzKG5ybWxfcm5hKSA8LSBucm1sX3JuYSRHZW5lIAoKbnJtbF9ybmEgPC0gZHBseXI6OnNlbGVjdChucm1sX3JuYSwgLUdlbmUpCgpjb2xuYW1lcyhucm1sX3JuYSkgPC0gY29sbmFtZXMobnJtbF9ybmEpICU+JSBnc3ViKHBhdHRlcm4gPSAiXlgqIiwgcmVwbGFjZW1lbnQgPSAiIikKCmNvbG5hbWVzKG5ybWxfcm5hKSA8LSBjb2xuYW1lcyhucm1sX3JuYSkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC4iLCByZXBsYWNlbWVudCA9ICItIikKCgoKbnJtbF9ybmEgPC0gIGNwbShucm1sX3JuYSwgbG9nID0gVCkgJT4lIHQoKSAlPiUgZGF0YS5mcmFtZSgpI0xvZyBub3JtYWxpemUKI25ybWxfcm5hIDwtIG5ybWxfcm5hICU+JSB0KCkgJT4lIGRhdGEuZnJhbWUoKQoKbnJtbF9ybmEgPC0gbnJtbF9ybmEgJT4lIG11dGF0ZShpZCA9IHJvdy5uYW1lcyguKSwgYmF0Y2ggPSAiTm9ybWFsIikgJT4lIG1lcmdlKGRwbHlyOjpzZWxlY3QobnJtbF9tZXRhICwgYyhpZCwgY2FzZXMuc3VibWl0dGVyX2lkKSApKQpucm1sX3JuYSA8LSBucm1sX3JuYSAlPiUgbXV0YXRlKGNhc2VzID0gY2FzZXMuc3VibWl0dGVyX2lkLCBQdXJpdHkgPSBOQSwgR3JhZGVfTXV0YXRpb25hbF9zdGF0dXMgPU5BKQpgYGAKCgoKI0Rvd25sb2FkIFRDR0EgUFJBRCBzYW1wbGUgbGlzdApgYGB7cn0KCnByYWRfbWV0YTwtIG1ybmFfcXVlcnkkcmVzdWx0c1tbMV1dICU+JSBkcGx5cjo6ZmlsdGVyKHNhbXBsZV90eXBlID09ICJQcmltYXJ5IFR1bW9yIikKI0dEQ2Rvd25sb2FkKG1ybmFfcXVlcnksIG1ldGhvZCA9ICJhcGkiLCBkaXJlY3RvcnkgPSAiL1VzZXJzL2RzL0Rlc2t0b3AiKQpgYGAKCgoKI1Byb2Nlc3MgUFJBRCBjb3VudHMKYGBge3J9CmZ1bGxfcGF0aCA8LSAiL1VzZXJzL2RzL0Rlc2t0b3AvcHJvamVjdHMvVENHQS9UQ0dBLVBSQUQtVHVtb3IvaGFybW9uaXplZC9UcmFuc2NyaXB0b21lX1Byb2ZpbGluZy9HZW5lX0V4cHJlc3Npb25fUXVhbnRpZmljYXRpb24vIgoKcHJhZF9ybmEgPC0gZG8uY2FsbChjYmluZCwgbGFwcGx5KGxpc3QuZmlsZXMocGF0aCA9IGZ1bGxfcGF0aCksIEZVTiA9IGZ1bmN0aW9uKGYpewogIHByaW50KHBhc3RlMCgicHJvY2Vzc2luZzogIixsaXN0LmZpbGVzKHBhdGggPSBwYXN0ZTAoZnVsbF9wYXRoLCBmKSkpKQogIGNvdW50cyA8LSByZWFkX3RzdihmaWxlID0gbGlzdC5maWxlcyhwYXRoID0gcGFzdGUwKGZ1bGxfcGF0aCwgZiksIGZ1bGwubmFtZXMgPSBUKSwgc2tpcCA9IDYsIGNvbF9uYW1lcyA9IEYgKQogIAogIHJldHVybihkYXRhLmZyYW1lKGYgPSBjb3VudHNbLDRdKSkKICAKICAKfSkpCiNwcmFkX3JuYSA8LSBjcG0ocHJhZF9ybmEsIGxvZyA9IFQsIHByaW9yLmNvdW50ID0gMSkgJT4lIGRhdGEuZnJhbWUoKQpjb2xuYW1lcyhwcmFkX3JuYSkgPC0gbGlzdC5maWxlcyhwYXRoID0gZnVsbF9wYXRoKQoKc3ltYm9scyA8LSByZWFkX3RzdihmaWxlID0gIi9Vc2Vycy9kcy9EZXNrdG9wL3Byb2plY3RzL1RDR0EvVENHQS1QUkFELVR1bW9yL2hhcm1vbml6ZWQvVHJhbnNjcmlwdG9tZV9Qcm9maWxpbmcvR2VuZV9FeHByZXNzaW9uX1F1YW50aWZpY2F0aW9uLzAwMDc4ODhmLThkOTYtNGMwMS04MjUxLTdmZWY2Y2M3MTU5Ni84ODIxNWRkMC01ODQxLTQ0ZjEtOTM5My1lZWZkODIzOGNiYjMucm5hX3NlcS5hdWdtZW50ZWRfc3Rhcl9nZW5lX2NvdW50cy50c3YiLCBza2lwID0gNiwgY29sX25hbWVzID0gRilbLDJdCgpwcmFkX3JuYSRHZW5lIDwtIHN5bWJvbHMkWDIKCgojd3JpdGUudGFibGUoeCA9IHByYWRfcm5hLCBmaWxlID0gIi9Vc2Vycy9kcy9EZXNrdG9wL1RDR0EvVENHQS1QUkFELVR1bW9yL3ByYWRfcm5hX2NwbS50eHQiLCBxdW90ZSA9IEYsIHNlcCA9ICJcdCIsIHJvdy5uYW1lcyA9IEYsIGNvbC5uYW1lcyA9IFQpCgp3cml0ZS50YWJsZSh4ID0gcHJhZF9ybmEsIGZpbGUgPSAiL1VzZXJzL2RzL0Rlc2t0b3AvcHJvamVjdHMvVENHQS9UQ0dBLVBSQUQtVHVtb3IvcHJhZF9ybmFfY291bnRzLnR4dCIsIHF1b3RlID0gRiwgc2VwID0gIlx0Iiwgcm93Lm5hbWVzID0gRiwgY29sLm5hbWVzID0gVCkKYGBgCgoKI0Zvcm1hdCBQUkFEIGNvdW50IGRhdGEKYGBge3J9CiNwcmFkX3JuYSA8LSByZWFkLnRhYmxlKGZpbGUgPSAiL1VzZXJzL2RzL0Rlc2t0b3AvVENHQS9UQ0dBLVBSQUQtVHVtb3IvcHJhZF9ybmFfY3BtLnR4dCIsIGhlYWRlciA9IFQpCgpwcmFkX3JuYSA8LSByZWFkLnRhYmxlKGZpbGUgPSAiL1VzZXJzL2RzL0Rlc2t0b3AvcHJvamVjdHMvVENHQS9UQ0dBLVBSQUQtVHVtb3IvcHJhZF9ybmFfY291bnRzLnR4dCIsIGhlYWRlciA9IFQpCnByYWRfcm5hIDwtIHByYWRfcm5hWyFkdXBsaWNhdGVkKHByYWRfcm5hJEdlbmUpLF0KCgpyb3cubmFtZXMocHJhZF9ybmEpIDwtIHByYWRfcm5hJEdlbmUgCgpwcmFkX3JuYSA8LSBkcGx5cjo6c2VsZWN0KHByYWRfcm5hLCAtR2VuZSkKCmNvbG5hbWVzKHByYWRfcm5hKSA8LSBjb2xuYW1lcyhwcmFkX3JuYSkgJT4lIGdzdWIocGF0dGVybiA9ICJeWCoiLCByZXBsYWNlbWVudCA9ICIiKQoKY29sbmFtZXMocHJhZF9ybmEpIDwtIGNvbG5hbWVzKHByYWRfcm5hKSAlPiUgZ3N1YihwYXR0ZXJuID0gIlxcLiIsIHJlcGxhY2VtZW50ID0gIi0iKQoKcHJhZF9ybmEgPC0gIGNwbShwcmFkX3JuYSwgbG9nID0gVCkgJT4lIHQoKSAlPiUgZGF0YS5mcmFtZSgpI0xvZyBub3JtYWxpemUgZm9yIGhlYXRtYXAKI3ByYWRfcm5hIDwtIHByYWRfcm5hICU+JSB0KCkgJT4lIGRhdGEuZnJhbWUoKSNDb3VudHMgZm9yIERFRyBhbmFseXNpcwoKCgpwcmFkX3JuYSA8LSBwcmFkX3JuYSAlPiUgbXV0YXRlKGlkID0gcm93Lm5hbWVzKC4pLCBiYXRjaCA9ICJQUkFEIikgJT4lIG1lcmdlKGRwbHlyOjpzZWxlY3QocHJhZF9tZXRhICwgYyhpZCwgY2FzZXMuc3VibWl0dGVyX2lkKSApKQoKCgoKYGBgCgoKCiNBZGQgUFJBRCBwdXJpdHkgZnJvbSBHREMgd2Vic2l0ZQpgYGB7cn0KYW5ub19wcmFkIDwtIHJlYWQuY3N2KGZpbGUgPSAiL1VzZXJzL2RzL0Rlc2t0b3AvcHJvamVjdHMvVENHQS9UQ0dBLVBSQUQtVHVtb3IvcHJhZF9zdXBwLmNzdiIsIGhlYWRlciA9IFQpCmFubm9fcHJhZCA8LSBhbm5vX3ByYWQgJT4lIGRwbHlyOjpzZWxlY3QoYXZnUk5BX3B1cml0eSwgUEFUSUVOVF9JRCwgUmV2aWV3ZWRfR2xlYXNvbl9zdW0pCgoKcHJhZF9ybmEgPC0gaW5uZXJfam9pbihwcmFkX3JuYSwgYW5ub19wcmFkLCBieSA9IGMoImNhc2VzLnN1Ym1pdHRlcl9pZCIgPSAiUEFUSUVOVF9JRCIpKSAlPiUgbXV0YXRlKFB1cml0eSA9IGF2Z1JOQV9wdXJpdHkgKiAxMDAsIGNhc2VzID0gY2FzZXMuc3VibWl0dGVyX2lkLCBHcmFkZV9NdXRhdGlvbmFsX3N0YXR1cyA9IFJldmlld2VkX0dsZWFzb25fc3VtKQoKCmFubm9fcHJhZAoKYGBgCgoKCiNGb3JtYXQgbUNSUEMgY291bnQgZGF0YQpgYGB7cn0KYW5ub19tY3JwYyA8LSByZWFkLnRhYmxlKCIvVXNlcnMvZHMvRGVza3RvcC9wcm9qZWN0cy9kYXRhL2Fubm8vMjAyMDA5X2RlZXBSTkFzZXFfc2FtcGxlX2Z1bGwudHh0IiwgaGVhZGVyID1UKQoKCgoKYW5ub19tY3JwYyA8LSBhbm5vX21jcnBjICU+JSBkcGx5cjo6c2VsZWN0KGMoc2FtcGxlX2lkLCB3Z3NfaWQsIGJpb3BzeV9zaXRlLHR1bW9yX3B1cml0eV93Z3MsIHR1bW9yX3B1cml0eV9ybmEgLCB0dW1vcl9wdXJpdHlfaGlzdCwgQVIpKQoKCmFubm9fbWNycGMgPC0gYW5ub19tY3JwYyAlPiUgbXV0YXRlKGNhc2VzID0gIHNhbXBsZV9pZCwgUHVyaXR5ID0gdHVtb3JfcHVyaXR5X3JuYSwgR3JhZGVfTXV0YXRpb25hbF9zdGF0dXMgPUFSKSAlPiUgZHBseXI6OnNlbGVjdChjYXNlcywgUHVyaXR5LCBHcmFkZV9NdXRhdGlvbmFsX3N0YXR1cykKCgoKbWNycGNfcm5hIDwtIHJlYWQudGFibGUoZmlsZSA9ICIvVXNlcnMvZHMvRGVza3RvcC9wcm9qZWN0cy9kYXRhL3JuYS9tQ1JQQ19STkFfY291bnRzX2dlbmVuYW1lLnR4dCIsIGhlYWRlciA9IFQpCm1jcnBjX3JuYSA8LSBtY3JwY19ybmFbIWR1cGxpY2F0ZWQobWNycGNfcm5hJEdlbmVuYW1lKSxdCgoKCgpyb3cubmFtZXMobWNycGNfcm5hKSA8LSBtY3JwY19ybmEkR2VuZW5hbWUKbWNycGNfcm5hIDwtIG1jcnBjX3JuYVssLTFdCm1jcnBjX3JuYSA8LSBjcG0obWNycGNfcm5hLCBsb2cgPSBUKSAlPiUgdCgpICU+JSBkYXRhLmZyYW1lKCkjTG9nIG5vcm1hbGl6ZSBmb3IgaGVhdG1hcAojbWNycGNfcm5hIDwtIG1jcnBjX3JuYSAlPiUgdCgpICU+JSBkYXRhLmZyYW1lKCkjQ291bnRzIGZvciBERUcgYW5hbHlzaXMKcm93Lm5hbWVzKG1jcnBjX3JuYSkgPC0gZ3N1YigiXFwuIiwgIi0iLCAgeCA9IHJvdy5uYW1lcyhtY3JwY19ybmEpKQoKCgptY3JwY19ybmEgPC0gbWNycGNfcm5hICU+JSBtdXRhdGUoY2FzZXMgPSByb3cubmFtZXMoLiksIGJhdGNoID0gIm1DUlBDIikKCiNBZGQgbUNSUEMgcHVyaXR5Cm1jcnBjX3JuYSA8LSBtY3JwY19ybmEgJT4lIG1lcmdlKGFubm9fbWNycGMpCgoKCmBgYAoKI01lcmdlIFBSQUQgYW5kIG1DUlBDIGRhdGFzZXRzIChERUcgYW5hbHlzaXMpCmBgYHtyfQoKcXVlcnkgPC0gaW50ZXJzZWN0KGNvbG5hbWVzKHByYWRfcm5hKSwgY29sbmFtZXMobWNycGNfcm5hKSkjR2V0IGxuY1JOQXMgaW4gY29tbW9uICsgY2FzZXMgKyBwdXJpdHkKCihsZW5ndGgocXVlcnkpLTIpL2xlbmd0aCggbGluYyRnZW5lLm5hbWUpICMlIG9mIGxuY1JOQXMgY29tbW9uIGFjcm9zcyBkYXRhc2V0cwoKI0NvbWJpbmUgUFJBRCBhbmQgbUNSUEMgLSByb3dzIGFyZSBzYW1wbGVzIGFuZCBjb2x1bW5zIGFyZSBsbmNSTkFzICsgUk5BIHB1cml0eQpybmEgPC0gcmJpbmQocHJhZF9ybmFbLHF1ZXJ5XSwgbWNycGNfcm5hWyxxdWVyeV0pCgoKcm5hCgpgYGAKCiNNZXJnZSBQUkFELCBOb3JtYWwsIGFuZCBtQ1JQQyBkYXRhc2V0cyAoSGVhdG1hcCkKYGBge3J9CnF1ZXJ5IDwtIGludGVyc2VjdChjb2xuYW1lcyhwcmFkX3JuYSksIGNvbG5hbWVzKG1jcnBjX3JuYSkpICU+JSBpbnRlcnNlY3QoIGNvbG5hbWVzKG5ybWxfcm5hKSkjR2V0IGxuY1JOQXMgaW4gY29tbW9uICsgY2FzZXMgKyBwdXJpdHkKCiNDb21iaW5lIFBSQUQgYW5kIG1DUlBDIC0gcm93cyBhcmUgc2FtcGxlcyBhbmQgY29sdW1ucyBhcmUgbG5jUk5BcyArIFJOQSBwdXJpdHkgKyBiYXRjaApjb21iX3JuYSA8LSByYmluZCggbnJtbF9ybmFbLHF1ZXJ5XSwgYXJyYW5nZShwcmFkX3JuYVsscXVlcnldLEdyYWRlX011dGF0aW9uYWxfc3RhdHVzKSwgYXJyYW5nZShtY3JwY19ybmFbLHF1ZXJ5XSxHcmFkZV9NdXRhdGlvbmFsX3N0YXR1cykpCgoKY29tYl9ybmEgPC0gZGF0YS5mcmFtZShjb21iX3JuYVssYygiYmF0Y2giLCAiUHVyaXR5IiwgImNhc2VzIiwgIkdyYWRlX011dGF0aW9uYWxfc3RhdHVzIildLCBjb21iX3JuYVssY29sbmFtZXMoY29tYl9ybmEpICVpbiUgYyhwY2FfbG5jcm5hLCBub3RwY2FfbG5jcm5hKV0pCgoKY29tYl9ybmEgPC0gY29tYl9ybmEgJT4lIG11dGF0ZShjYXNlcyA9IHBhc3RlMChjYXNlcywgIjoiLCAxOm5yb3coY29tYl9ybmEpKSkKCgpyb3cubmFtZXMoY29tYl9ybmEpIDwtIGNvbWJfcm5hJGNhc2VzCmNvbWJfcm5hJGJhdGNoICU+JSB0YWJsZSgpCgoKCmBgYAoKCgojUGxvdHRpbmcgaGVhdG1hcCBvZiBwcm9ncmVzc2lvbiBmb3IgcHJvc3RhdGUgbG5jUk5BCmBgYHtyfQptYXQgPC0gY29tYl9ybmFbLGNvbG5hbWVzKGNvbWJfcm5hKSAlaW4lIHBjYV9sbmNybmFdCgpmaWx0IDwtIHQobWF0KVthcHBseSh0KG1hdCksIDEsIEZVTiA9IGZ1bmN0aW9uKHgpe3N1bSh4IDwgMCl9KSA9PSBuY29sKHQobWF0KSksXSAlPiUgcm93Lm5hbWVzKCkKCm1hdCA8LSBtYXRbLCFjb2xuYW1lcyhtYXQpICVpbiUgZmlsdF0KCmFubm8gPC0gZHBseXI6OnNlbGVjdChjb21iX3JuYSwgYyhiYXRjaCwgUHVyaXR5LCBHcmFkZV9NdXRhdGlvbmFsX3N0YXR1cykpCgoKY29sbmFtZXMoYW5ubykgPC0gYygiQmF0Y2giLCAiUk5BLlR1bW9yLlB1cml0eSIsICJHUy5NdXRhdGlvbmFsLnN0YXR1cyIpCmFubm8gPC0gbXV0YXRlKGFubm8sIEdTLk11dGF0aW9uYWwuc3RhdHVzID0gaWZlbHNlKEdTLk11dGF0aW9uYWwuc3RhdHVzID09IDIsICJBUiBXVCIsIGlmZWxzZShHUy5NdXRhdGlvbmFsLnN0YXR1cyA9PSAzLCAiQVIgR2FpbiIsIEdTLk11dGF0aW9uYWwuc3RhdHVzKSkpCgphbm5vX2NvbCA8LSBsaXN0KEJhdGNoID1jb2xvclJhbXBQYWxldHRlKGMoJ2RhcmtncmVlbicsImJsYWNrIiwgInB1cnBsZSIpKSgzKSkgIywgUk5BLlR1bW9yLlB1cml0eSA9IGNvbG9yUmFtcFBhbGV0dGUoYygiZ3JleSIsICJuYXZ5IikpKDUwMCkgKQpuYW1lcyhhbm5vX2NvbCRCYXRjaCkgPC0gYW5ubyRCYXRjaCAlPiUgdW5pcXVlKCkKCgphbm5vCmNvbHVtbl9oYSA9IEhlYXRtYXBBbm5vdGF0aW9uKCBSTkEuVHVtb3IuUHVyaXR5ID0gYW5ubyRSTkEuVHVtb3IuUHVyaXR5LCBCYXRjaCA9IGFubm8kQmF0Y2gsIGNvbCA9IGFubm9fY29sICwgR1MuTXV0YXRpb25hbC5zdGF0dXMgPSBhbm5vJEdTLk11dGF0aW9uYWwuc3RhdHVzKQoKcGRmKCIvVXNlcnMvZHMvRGVza3RvcC9wbG90LnBkZiIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDEwKQpIZWF0bWFwKG1hdHJpeCA9IHQobWF0KSwgc2hvd19jb2x1bW5fbmFtZXMgPSBGLCBjb2wgID0gY29sb3JSYW1wUGFsZXR0ZShjKCduYXZ5Jywid2hpdGUiLCAicmVkIikpKDEwKSwgdG9wX2Fubm90YXRpb24gPSBjb2x1bW5faGEsIGNsdXN0ZXJfY29sdW1ucyA9IEYsIHJvd19uYW1lc19ncCA9IGdwYXIoZm9udHNpemUgPSA1LGNvbCA9IGlmZWxzZShjb2xuYW1lcyhtYXQpICVpbiUgYyh1bmlxdWUodXAkR2VuZXMpKSAsICJyZWQiLCBpZmVsc2UoY29sbmFtZXMobWF0KSAgJWluJSBjKHVuaXF1ZShkb3duJEdlbmVzKSksICJibHVlIiwgImJsYWNrIikpKSkKZGV2Lm9mZigpCgptYXQKCmBgYAoKCgojUGxvdCBsbmNSTkFzIGluIFRNRQpgYGB7cn0KCmFubm9fY29sIDwtIGRwbHlyOjpzZWxlY3QoY29tYl9ybmEsIGMoYmF0Y2gsIFB1cml0eSwgR3JhZGVfTXV0YXRpb25hbF9zdGF0dXMpKQoKCmNvbG5hbWVzKGFubm9fY29sKSA8LSBjKCJCYXRjaCIsICJSTkEuVHVtb3IuUHVyaXR5IiwgIkdTLk11dGF0aW9uYWwuc3RhdHVzIikKYW5ub19jb2wgPC0gbXV0YXRlKGFubm9fY29sLCBHUy5NdXRhdGlvbmFsLnN0YXR1cyA9IGlmZWxzZShHUy5NdXRhdGlvbmFsLnN0YXR1cyA9PSAyLCAiQVIgV1QiLCBpZmVsc2UoR1MuTXV0YXRpb25hbC5zdGF0dXMgPT0gMywgIkFSIEdhaW4iLCBHUy5NdXRhdGlvbmFsLnN0YXR1cykpKQoKCm1hdCA8LSBjb21iX3JuYVssY29sbmFtZXMoY29tYl9ybmEpICVpbiUgbm90cGNhX2xuY3JuYV0gJT4lIHQoKSAlPiUgZGF0YS5mcmFtZSgpICU+JSBtdXRhdGUoZ2VuZSA9IHJvdy5uYW1lcyguKSkgJT4lIGlubmVyX2pvaW4oZmluYWxfbWFya2VycykgJT4lIGFycmFuZ2UoY2x1c3RlcikgCnJvdy5uYW1lcyhtYXQpIDwtbWF0JGdlbmUgCgphbm5vX3JvdyA8LSBtYXQgJT4lIGRwbHlyOjpzZWxlY3QoY2x1c3RlcikKY29sbmFtZXMoYW5ub19yb3cpIDwtIGMoIkNlbGwudHlwZSIpCgptYXQgPC0gbWF0ICU+JSBkcGx5cjo6c2VsZWN0KHN0YXJ0c193aXRoKGMoIlRDR0EiLCAiRFRCIiwgIlBSIikpKQoKCgoKCgoKZmlsdCA8LSBtYXRbYXBwbHkobWF0LCAxLCBGVU4gPSBmdW5jdGlvbih4KXtzdW0oeCA8IDApfSkgPT0gbmNvbChtYXQpLF0gJT4lIHJvdy5uYW1lcygpCmZpbHQKbWF0IDwtIG1hdFshcm93bmFtZXMobWF0KSAlaW4lIGZpbHQsXQphbm5vX3JvdyA8LSBhbm5vX3Jvd1shcm93bmFtZXMoYW5ub19yb3cpICVpbiUgZmlsdCwsIGRyb3AgPSBGXQoKCmNvbHVtbl9oYSA9IEhlYXRtYXBBbm5vdGF0aW9uKCBSTkEuVHVtb3IuUHVyaXR5ID0gYW5ub19jb2wkUk5BLlR1bW9yLlB1cml0eSwgQmF0Y2ggPSBhbm5vX2NvbCRCYXRjaCwgR1MuTXV0YXRpb25hbC5zdGF0dXMgPSBhbm5vX2NvbCRHUy5NdXRhdGlvbmFsLnN0YXR1cykKcm93X2hhIDwtIHJvd0Fubm90YXRpb24oQ2VsbC50eXBlID0gYW5ub19yb3ckQ2VsbC50eXBlKQoKYW5ub19yb3cKcGRmKCIvVXNlcnMvZHMvRGVza3RvcC9wbG90LnBkZiIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDEwKQpIZWF0bWFwKG1hdHJpeCA9IG1hdCwgc2hvd19jb2x1bW5fbmFtZXMgPSBGLCBjb2wgID0gY29sb3JSYW1wUGFsZXR0ZShjKCduYXZ5Jywid2hpdGUiLCAicmVkIikpKDEwKSwgdG9wX2Fubm90YXRpb24gPSBjb2x1bW5faGEsIGNsdXN0ZXJfY29sdW1ucyA9IEYsbGVmdF9hbm5vdGF0aW9uID0gcm93X2hhLCByb3dfbmFtZXNfZ3AgPSBncGFyKGZvbnRzaXplID0gNSxjb2wgPSBpZmVsc2Uocm93bmFtZXMobWF0KSAlaW4lIGModW5pcXVlKHVwJEdlbmVzKSkgLCAicmVkIiwgaWZlbHNlKHJvd25hbWVzKG1hdCkgICVpbiUgYyh1bmlxdWUoZG93biRHZW5lcykpLCAiYmx1ZSIsICJibGFjayIpKSksIHJvd19zcGxpdCA9IGFubm9fcm93JENlbGwudHlwZSkKZGV2Lm9mZigpCgpsZW5ndGgobm90cGNhX2xuY3JuYSkKCmRpbShtYXQpCgpsZW5ndGgoZmlsdCkKbWF0CmRpbShtYXQpCgoKY29sbmFtZXMobWF0KQoKYGBgCgo=